package com.sob.bountyhunter;

import java.io.File;
import java.io.IOException;
import java.lang.Character.Subset;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.Font;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Art {
	//Tabla para las animaciones con cuatro direcciones
	private static HashMap <String, Animation[]> anims;
	
	public static SpriteSheet objetos32x32=loadSpriteSheet("/res/objetos 32x32.png", 32, 32);	
	public static SpriteSheet objetos32x64=loadSpriteSheet("/res/objetos 32x64.png", 32, 64);	
	public static SpriteSheet ventana=loadSpriteSheet("/res/window16.png", 16, 16);	
	public static SpriteSheet iconosTexto=loadSpriteSheet("/res/textIcons.png", 16, 16);	
	
	public static Image []armas = { loadSprite("/res/shortsword.png"),
									loadSprite("/res/longsword.png") };
	
	public static UnicodeFont defaultFont=loadFontTTF("/res/fonts/ARLRDBD.TTF", 16);
	public static UnicodeFont defaultBigFont=loadFontTTF("/res/fonts/ARLRDBD.TTF", 24);

	
	
	private static UnicodeFont loadFontTTF(String name, int size){
		UnicodeFont res=null;
		try {
			res=new UnicodeFont(name,size,true,false);
			res.addAsciiGlyphs();
			res.addGlyphs(400, 600);
			res.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
			res.loadGlyphs();
		} catch (SlickException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
		return res;
	}

	private static Image loadSprite(String f){
		Image res=null;
		
		try{
			res=new Image(f, new Color(0xFF00FF));
		}catch(SlickException e){
			e.printStackTrace();
		}
		
		return res;
	}

	private static SpriteSheet loadSpriteSheet(String f, int tw, int th){
		SpriteSheet res=null;
		
		try{
			res=new SpriteSheet(f, tw, th, new Color(0xFF00FF));
		}catch(SlickException e){
			e.printStackTrace();
		}
		
		return res;
	}
	
	/**
	 * Obtiene una animacion (con varias direcciones posibles) guardada
	 * @param name Nombre de la animacion
	 * @return
	 */
	public static Animation[] getAnim(String name){		
		Animation[] anim=null;
		
		Animation[] tAnim=anims.get(name);
		
		anim=new Animation[tAnim.length];
		
		//Copia la animacion y devuelve la copia 
		//(Temporal, no se si seria mejor crearla desde el archivo para que ocupe menos memoria)
		for(int i=0;i<anim.length;i++){
			anim[i]=tAnim[i].copy();
		}
		
		
		return anim;
	}
	
	/**
	 * Carga una animacion desde un archivo xml
	 * @param fileName Ruta del archivo (sin el .xml)
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws SlickException
	 */
	public static void loadAnimation(String fileName) throws ParserConfigurationException, SAXException, IOException, SlickException{
		XmlAnimDef []defs=loadXmlAnimFile(fileName);
		
		//Si, aun no se ha inicializado la tabla, lo hace
		if(anims==null){
			anims=new HashMap<String, Animation[]>();
		}
		
		//Carga y guarda la animacion
		for(XmlAnimDef animDef: defs){
			Animation[] anim=loadPngAnimFile(animDef);
			anims.put(animDef.name, anim);			
		}
	}
		
	private static Animation[] loadPngAnimFile(XmlAnimDef animDef) throws SlickException{
		
		Animation []animacion;		
		//Carga la plantilla
		SpriteSheet archivo=new SpriteSheet("/res/anims/"+animDef.file, animDef.spriteWidth, animDef.spriteHeight, new Color(0xFF00FF));
		
		//Define las animaciones para las X direcciones
		animacion=new Animation[animDef.numDirs];
		for(int i=0;i<animDef.numDirs;i++){
			animacion[i]=new Animation();
			
			//Define cada frame
			for(int j=0;j<animDef.frameTime.length;j++){
				Image img=archivo.getSubImage(j, i+animDef.startRow);
				animacion[i].addFrame(img, animDef.frameTime[j]);				
			}
			
			animacion[i].setAutoUpdate(false);
			animacion[i].setCurrentFrame(-1);
			animacion[i].setLooping(animDef.loop);			

		}
		
		return animacion;
	}
	
	private static XmlAnimDef[] loadXmlAnimFile(String fileName) throws ParserConfigurationException, SAXException, IOException{
		File file=new File(fileName+".xml");
		DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
		DocumentBuilder db=dbf.newDocumentBuilder();
		Document doc=db.parse(file);
		doc.getDocumentElement().normalize();
		
		//Obtiene la lista de elementos Animation
		NodeList animsList=doc.getElementsByTagName("animation");
		XmlAnimDef []animDefs=new XmlAnimDef[animsList.getLength()];
		
		//Los recorre
		for(int i=0;i<animsList.getLength();i++){
			
			Element animElemt=(Element) animsList.item(i);
			
			//Obtiene los atributos
			String name=animElemt.getAttribute("name");
			String pngFileName=animElemt.getAttribute("file");
			String spriteWidth=animElemt.getAttribute("spriteWidth");
			String spriteHeight=animElemt.getAttribute("spriteHeight");
			String frames=animElemt.getAttribute("frames");
			String numDirs=animElemt.getAttribute("numDirs");
			String defaultTme=animElemt.getAttribute("defaultTime");
			String startRow=animElemt.getAttribute("startRow");
			String loop=animElemt.getAttribute("loop");
			
			//Guarda los atributos
			animDefs[i]=new XmlAnimDef(frames);
			animDefs[i].name=name;
			animDefs[i].file=pngFileName;
			animDefs[i].setSpriteWidth(spriteWidth);
			animDefs[i].setSpriteHeight(spriteHeight);
			animDefs[i].setStartRow(startRow);
			animDefs[i].setNumDirs(numDirs);
			animDefs[i].setDefaultTime(defaultTme);
			animDefs[i].setLoop(loop);
			
			//Recorre la definicion de frames (opcional)
			NodeList frameList=animElemt.getElementsByTagName("frame");
			for(int j=0;j<frameList.getLength();j++){
				Element frameElemt=(Element) frameList.item(j);
				
				//Obtiene atributos y los guarda
				String frameNum=frameElemt.getAttribute("num");
				String frameTime=frameElemt.getAttribute("time");				
				animDefs[i].setTime(frameNum, frameTime);
			}
		}
		
		return animDefs; 
	}
	/*
	public static void drawTextInto(String s, float x, float y, boolean  hasShadow, Image img, UnicodeFont font, Graphics g){
		try {
			Graphics tg=img.getGraphics();
			Graphics.setCurrent(tg);
			drawText(s, x, y, hasShadow, font);
			Graphics.setCurrent(g);
		} catch (SlickException e) {
			e.printStackTrace();
		}

	}*/
	
	public static String getCleanString(String s){
		String res="";
		
		for(int i=0;i<s.length();i++){
			String subString=s.substring(i, i+1);
			if(subString.equals("{")){
				int fin=s.indexOf("}",i);
				i=fin;
				continue;
			}
			res+=subString;
		}
		
		return res;
	}
	
	public static void drawText(String s, float x, float y, boolean hasShadow, UnicodeFont font){
		int ancho=9;
		int pos=0;
		Color fontColor=Color.white;
		
		//String drawn="";
		int xOff=0;
		
		for(int i=0;i<s.length();i++){
			String subString=s.substring(i, i+1);
			
			//Si es un codigo especial
			if(subString.equals("{")){
				//Caracter de accion
				String accion=s.substring(i+1,i+2);
				
				//Parametro
				int endParamIndex=s.indexOf("}", i);
				String param=s.substring(i+2,endParamIndex);
				
				//Si la accion es cambiar el color
				if(accion.toUpperCase().equals("C")){
					int color=Integer.parseInt(param, 16);
					fontColor=new Color(color);
				//Insertar un icono
				}else if(accion.toUpperCase().equals("I")){
					int iconIndex=Integer.parseInt(param);
					Image img=iconosTexto.getSubImage(iconIndex, 0);
					
					int iH=img.getHeight();
					int fH=font.getHeight("1");
					
					img.draw(x+(xOff), y+(fH/2)-(iH/4));
					xOff+=img.getWidth();
					pos++;
				}
				
				i=endParamIndex;
				continue;
			}
			pos++;
			
			//int drawnOffset=Art.defaultFont.getWidth(drawn);
			if(hasShadow){			
				//g.setColor(Color.black);
				//g.drawString(subString, x+(pos*ancho)+1, y+1);
				//Art.defaultFont.getEffects().add(new ColorEffect(java.awt.Color.BLACK));
				font.drawString(x+xOff+1, y+1, subString, Color.black);
			}
			//g.setColor(fontColor);
			//g.drawString(subString, x+(pos*ancho), y);
			//int drawnOffset=Art.defaultFont.getWidth(drawn);
			//Art.defaultFont.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
			font.drawString(x+xOff, y, subString, fontColor);
			
			//drawn+=subString;
			xOff+=font.getWidth(subString);
		}
	}
}
